#pragma once
#include "net.hpp"
#include "message.hpp"

// 程序设计中遵循开闭原则：对修改关闭，对扩展开放
// 这使得我们可以在不修改现有代码的情况下添加新功能
//通过基类指针调用了子类重写的虚函数，允许Dispatcher类只依赖于抽象接口BaseConnection，而不需要知道具体的连接实现细节，符合依赖倒置原则

namespace bitrpc {

    // 回调基类：父类指针定义统一接口，实现多态调用
    class Callback {
    public:
        using ptr = std::shared_ptr<Callback>;

        // 纯虚函数，子类必须实现的消息处理接口
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
    };

    // 泛型回调类：为不同消息类型提供类型安全的回调包装
    template<typename T>
    class CallbackT : public Callback {
    public:
        using ptr = std::shared_ptr<CallbackT<T>>;
        // 定义回调函数类型：接收连接对象和具体类型的消息
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;

        CallbackT(const MessageCallback &handler) : _handler(handler) {}
        
        // 实现基类接口，内部进行类型转换并调用具体处理函数
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override {
            
            auto type_msg = std::dynamic_pointer_cast<T>(msg);      // 将基类消息指针转换为具体类型
            _handler(conn, type_msg);                               // 调用用户注册的具体处理函数[BaseConnection, BaseMessage]
        }
    private:
        MessageCallback _handler;  // 设置：存储用户注册的回调函数
    };

    // 消息分发器：统一管理不同类型消息的处理回调
    class Dispatcher {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        
        // 注册处理器：将消息类型与对应的处理函数关联
        template<typename T>
        void registerHandler(MType mtype, const typename CallbackT<T>::MessageCallback &handler) {          //注册
            std::unique_lock<std::mutex> lock(_mutex);
            
            auto cb = std::make_shared<CallbackT<T>>(handler);                                              // 创建类型安全的回调对象并存储
            _handlers.insert(std::make_pair(mtype, cb));
        }
        
        // 消息分发：根据消息类型找到并调用对应的处理函数
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) {
            std::unique_lock<std::mutex> lock(_mutex);
            
            auto it = _handlers.find(msg->mtype());                                                     // 查找消息类型对应的处理器
            if (it != _handlers.end()) {
                return it->second->onMessage(conn, msg);                                                // 通过多态调用具体类型的处理函数
            }           
            //问题:这个it不是基类指针吗?
            //在服务注册时，本质是[MType,Callback<T>]，指针实际指针或者存储为基类指针，父类指针统一管理
            ELOG("收到未知类型的消息:%d", msg->mtype());                                                  // 处理未注册类型的消息（正常情况下不应出现）
            conn->shutdown();
        }
    private:
        std::mutex _mutex;                                      // 保护并发访问
        std::unordered_map<MType, Callback::ptr> _handlers;     // 使用多态存储不同类型的回调处理器,通过类型管理不同的回调函数
    };

    //问题：如果不采用:CallbackT
    //用户注册回调函数时无法直接操作具体的消息类型，同时会重现代码重复的问题


    // 设计要点：
    // 1. 类型擦除：通过基类指针存储不同类型的处理器，解决容器存储异构类型的问题
    // 2. 类型安全：通过模板和动态类型转换，确保用户可以直接操作具体消息类型
    // 3. 回调机制：将消息处理逻辑解耦，便于扩展和维护
}
